﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using BusClustering.Dao;
using System.Threading;
using DevExpress.XtraMap;
using BusClustering.Utility;


namespace BusClustering
{
    public partial class Form1 : Form
    {
       

        public Form1()
        {
            InitializeComponent();
        }

        private void barSubItemClose_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.Close();
        }

        /*---------------------------------------------------*/
        private delegate void DelegateConvertData();
        private delegate void DelegateLoadDB();
        private delegate void DelegateViewPath();

        /*----------------------------------------------------*/
        private void ViewPath()
        {
            if (this.InvokeRequired || this.mapControlVision.InvokeRequired)
            {
                this.Invoke(new DelegateViewPath(ViewPath));
            }
            else
            {
                int iYearFrom = dateEditFrom.DateTime.Year;
                int iMonthFrom = dateEditFrom.DateTime.Month;
                int iDayFrom = dateEditFrom.DateTime.Day;
                int iHourFrom = timeEditFrom.Time.Hour;
                int iMinuteFrom = timeEditFrom.Time.Minute;
                DateTime dateFrom = new DateTime(iYearFrom, iMonthFrom, iDayFrom, iHourFrom, iMinuteFrom, 0);

                int iYearTo = dateEditTo.DateTime.Year;
                int iMonthTo = dateEditTo.DateTime.Month;
                int iDayTo = dateEditTo.DateTime.Day;
                int iHourTo = timeEditTo.Time.Hour;
                int iMinuteTo = timeEditTo.Time.Minute;
                DateTime dateTo = new DateTime(iYearTo, iMonthTo, iDayTo, iHourTo, iMinuteTo, 59);


                if (mapControlVision.Layers.Count != 0)
                {
                    mapControlVision.Layers.RemoveAt(1);
                }
                VectorItemsLayer VectorLayer = new VectorItemsLayer();
                mapControlVision.Layers.Add(VectorLayer);
                mapControlVision.ZoomLevel = 12;
                VectorLayer.Items.BeginUpdate();

                BusTrackingDao dao = new BusTrackingDao();
                try
                {
                    List<BusTracking> trackingList = dao.LoadTrackingListWithTimePeriodAndDeviceId(int.Parse(txtDeviceIdViewPath.Text.Trim()), dateFrom, dateTo);
                    if (trackingList.Count != 0)
                    {
                        for (int i = 0; i < trackingList.Count - 1; i++)
                        {
                            MapPushpin Pin = new DevExpress.XtraMap.MapPushpin();
                            Pin.Location = new GeoPoint(trackingList[i].Latitude, trackingList[i].Longitude);
                            mapControlVision.ToolTipController = new DevExpress.Utils.ToolTipController() { AllowHtmlText = true };
                            Pin.ToolTipPattern = BuildDeviceInfo(trackingList[i]);

                            //VectorLayer.Mappings.Type = "TypeField";
                            Pin.Image = imageCollectionNewPin.Images[6];
                            VectorLayer.Items.Add(Pin);

                            MapLine line = new DevExpress.XtraMap.MapLine();
                            line.Point1 = new GeoPoint(trackingList[i].Latitude, trackingList[i].Longitude);
                            line.Point2 = new GeoPoint(trackingList[i + 1].Latitude, trackingList[i + 1].Longitude);
                            line.StrokeWidth = 3;
                            VectorLayer.Items.Add(line);
                            Application.DoEvents();

                        }

                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Lỗi Nhập Liệu", MessageBoxButtons.OK);
                }
                VectorLayer.Items.EndUpdate();
            }
        }

        private void LoadDB()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DelegateLoadDB(LoadDB));
            }
            else
            {
                xtraTabPageViewDB.Select();
                BusTrackingDao dao = new BusTrackingDao();
                gridControlViewDB.DataSource = dao.LoadDatabase();
            }
        }

        private void ConvertData()
        {
            if (progressBarControlConvertFile.InvokeRequired || lblConvertFileProgress.InvokeRequired || tbxPath.InvokeRequired || btnPath.InvokeRequired || this.InvokeRequired)
            {
                this.Invoke(new DelegateConvertData(ConvertData));
            }
            else
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();


                openFileDialog.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
                openFileDialog.FilterIndex = 2;
                openFileDialog.RestoreDirectory = true;
                openFileDialog.Multiselect = true;
                openFileDialog.Title = "Please Select Source File(s)";

                if (System.Windows.Forms.DialogResult.OK == openFileDialog.ShowDialog())
                {

                    tbxPath.Text = Directory.GetParent(openFileDialog.FileName).FullName;

                    // Progress Bar and Label
                    progressBarControlConvertFile.Visible = true;
                    progressBarControlConvertFile.Properties.Step = 1;
                    progressBarControlConvertFile.Properties.PercentView = true;
                    progressBarControlConvertFile.Properties.Maximum = openFileDialog.FileNames.Length;
                    progressBarControlConvertFile.Properties.Minimum = 0;

                    lblConvertFileProgress.Visible = true;
                    lblShowRecord.Visible = true;

                    // Dao
                    BusTrackingDao dao = new BusTrackingDao();
                    // Read the files 
                    foreach (String file in openFileDialog.FileNames)
                    {
                        // Read 1 file
                        lblConvertFileProgress.Text = file;
                        Application.DoEvents();
                        StreamReader sr = new StreamReader(file);
                        try
                        {
                            sr.ReadLine();
                            while (!sr.EndOfStream)
                            {
                                try
                                {
                                    // 193|"10.8283516666667"|"106.601426666667"|"0.12"|"0"|"0"|"2012-11-11 08:18:05"
                                    string line = sr.ReadLine();
                                    
                                    lblShowRecord.Text = line;
                                    Application.DoEvents();
                                    String[] record = line.Replace('"', ' ').Split('|');

                                    BusTracking btTrackingInfo = new BusTracking();
                                    btTrackingInfo.DeviceId = int.Parse(record[0].Trim());
                                    btTrackingInfo.Latitude = float.Parse(record[1].Trim());
                                    btTrackingInfo.Longitude = float.Parse(record[2].Trim());
                                    btTrackingInfo.Speed = float.Parse(record[3].Trim());
                                    btTrackingInfo.Satellite = float.Parse(record[4].Trim());
                                    if ("0" == record[5].Trim())
                                    {
                                        btTrackingInfo.Lock = false;
                                    }
                                    else
                                    {
                                        btTrackingInfo.Lock = true;
                                    }
                                    string[] time = record[6].Trim().Replace(' ', '-').Replace(':', '-').Split('-');
                                    btTrackingInfo.TrackingTime = new DateTime(int.Parse(time[0].Trim()), int.Parse(time[1].Trim()), int.Parse(time[2].Trim()), int.Parse(time[3].Trim()), int.Parse(time[4].Trim()), int.Parse(time[5].Trim()));
                                    dao.Insert(btTrackingInfo);
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(ex.Message, "Xảy Ra Lỗi Khi Chuyển Dữ Liệu", MessageBoxButtons.OK);
                                }
                            }
                        }
                        finally
                        {
                            sr.Close();
                        }
                        progressBarControlConvertFile.PerformStep();
                        progressBarControlConvertFile.Update();
                        Application.DoEvents();
                        
                    }
                    progressBarControlConvertFile.Visible = false;
                    lblConvertFileProgress.Visible = false;
                    lblShowRecord.Visible = false;
                }
            }
        }

        private void btnPath_Click(object sender, EventArgs e)
        {
            Thread convertDataThread = new Thread(new ThreadStart(ConvertData));
            convertDataThread.Start();
        }

        private void navBarItemView_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e)
        {
            xtraTabControl.SelectedTabPage = xtraTabPageViewDB;
            xtraTabPageSetting.PageVisible = false;
            xtraTabPageUtilities.PageVisible = false;
            xtraTabPageViewDB.PageVisible = true;
            xtraTabPageVision.PageVisible = false;
            Thread loadDBThread = new Thread(new ThreadStart(LoadDB));
            loadDBThread.Start();
           
        }

        private void navBarItemMainView_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e)
        {
            xtraTabControl.SelectedTabPage = xtraTabPageVision;
            xtraTabPageSetting.PageVisible = false;
            xtraTabPageUtilities.PageVisible = false;
            xtraTabPageViewDB.PageVisible = false;
            xtraTabPageVision.PageVisible = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            xtraTabControl.SelectedTabPage = xtraTabPageVision;
            xtraTabPageSetting.PageVisible = false;
            xtraTabPageUtilities.PageVisible = false;
            xtraTabPageViewDB.PageVisible = false;
            xtraTabPageVision.PageVisible = true;

            VectorItemsLayer VectorLayer = new VectorItemsLayer();
            mapControlVision.Layers.Add(VectorLayer);
        }

        private void mapControlVision_MouseClick(object sender, MouseEventArgs e)
        {
            //MapHitInfo info = this.mapControlVision.CalcHitInfo(e.Location);
            //if (info.InMapPushpin)
            //{
            //    MapPushpin pin = (MapPushpin)info.MapPushpin;
            //    MessageBox.Show(pin.Location.Latitude.ToString());


            //}
        }

        private string BuildDeviceInfo(BusTracking pointTracking)
        {
            string sInfo = "<b>Thông Tin Thiết Bị:</b>\n";
            sInfo += "<b>Id: " + pointTracking.DeviceId.ToString() + "</b>\n";
            sInfo += "<b>Tọa Độ: " + pointTracking.Latitude.ToString() + " " + pointTracking.Longitude.ToString() + "</b>\n";
            sInfo += "<b>Tốc Độ: " + pointTracking.Speed.ToString() + "</b>\n";
            sInfo += "<b>Vệ Tinh: " + pointTracking.Satellite.ToString() + "</b>\n";
            sInfo += "<b>Bị Khóa: " + pointTracking.Lock.ToString() + "</b>\n";
            sInfo += "<b>Thời Điểm: " + pointTracking.TrackingTime.ToString() + "</b>\n";
            return sInfo;
        }

        private Dictionary<int, BusTracking> RemoveDuplication(List<BusTracking> trackingList)
        {
            List<BusTracking> newListBusTracking = new List<BusTracking>();
            Dictionary<int, BusTracking> dicBusTracking = new Dictionary<int, BusTracking>();
            foreach (BusTracking trackingPoint in trackingList)
            {
                if (!dicBusTracking.ContainsKey(trackingPoint.DeviceId))
                {
                    dicBusTracking.Add(trackingPoint.DeviceId, trackingPoint); 
                }
            }
            return dicBusTracking;
        }

        private void btnViewDensity_Click(object sender, EventArgs e)
        {
            if (mapControlVision.Layers.Count != 0)
            {
                mapControlVision.Layers.RemoveAt(1);
            }
            VectorItemsLayer VectorLayer = new VectorItemsLayer();
            mapControlVision.Layers.Add(VectorLayer);
            mapControlVision.ZoomLevel = 12;
            VectorLayer.Items.BeginUpdate();

            int iYear = dateEditPointTime.DateTime.Year;
            int iMonth = dateEditPointTime.DateTime.Month;
            int iDay = dateEditPointTime.DateTime.Day;
            int iHour = timeEditPointTime.Time.Hour;
            int iMinute = timeEditPointTime.Time.Minute;

            BusTrackingDao dao = new BusTrackingDao();
            List<BusTracking> trackingList = dao.LoadTrackingListWithTimePoint(iYear, iMonth, iDay, iHour, iMinute, 0, int.Parse(txtBound.Text));

            Dictionary<int, BusTracking> dictTracking = RemoveDuplication(trackingList);
            // Cluster
            if (checkEditCluster.Checked) 
            {
                if (trackingList.Count != 0)
                {
                    List<BusTracking> newlstTracking = new List<BusTracking>();
                    foreach (KeyValuePair<int, BusTracking> trackingPoint in dictTracking)
                    {
                        newlstTracking.Add(trackingPoint.Value);
                    }

                    List<MyPoint> pointLst = Utils.Cluster(newlstTracking, double.Parse(txtEpsilonCluster.Text), 3);

                    foreach (MyPoint point in pointLst)
                    {
                        MapPushpin Pin = new DevExpress.XtraMap.MapPushpin();
                        Pin.Location = new GeoPoint(point.Tracking.Latitude, point.Tracking.Longitude);
                        mapControlVision.ToolTipController = new DevExpress.Utils.ToolTipController() { AllowHtmlText = true };
                        Pin.ToolTipPattern = BuildDeviceInfo(point.Tracking);
                      
                        //VectorLayer.Mappings.Type = "TypeField";
                        Pin.Image = imageCollectionNewPin.Images[point.Tracking.DeviceId % 7];

                        VectorLayer.Items.Add(Pin);
                        
                    }
                }
            }
            else
            {
                

              

                int iNumOfBus = 0;
                string sBusInfo = "";
               
                if (trackingList.Count != 0)
                {
                    

                    foreach (KeyValuePair<int, BusTracking> trackingPoint in dictTracking)
                    {

                        MapPushpin Pin = new DevExpress.XtraMap.MapPushpin();
                        Pin.Location = new GeoPoint(trackingPoint.Value.Latitude, trackingPoint.Value.Longitude);
                        mapControlVision.ToolTipController = new DevExpress.Utils.ToolTipController() { AllowHtmlText = true };
                        Pin.ToolTipPattern = BuildDeviceInfo(trackingPoint.Value);
                        sBusInfo += Pin.ToolTipPattern + "\n";
                        sBusInfo += "--------------------\n";
                        //VectorLayer.Mappings.Type = "TypeField";
                        Pin.Image = imageCollectionNewPin.Images[0];

                        VectorLayer.Items.Add(Pin);
                        iNumOfBus++;
                    }
                }
               
                VectorLayer.Items.EndUpdate();
                rtxClusterInfo.Clear();
                rtxClusterInfo.AppendText("Thông Tin\n");
                rtxClusterInfo.AppendText("Số Lượng Xe Được Giám Sát: ");
                rtxClusterInfo.AppendText(iNumOfBus.ToString());
                rtxClusterInfo.AppendText("\n");
                rtxClusterInfo.AppendText("=====================\n");
                rtxClusterInfo.AppendText(sBusInfo);
            }
        }

        private void btnViewPath_Click(object sender, EventArgs e)
        {
            Thread viewPathThread = new Thread(new ThreadStart(ViewPath));
            viewPathThread.Start();
        }

        private void btnFindCordinate_Click(object sender, EventArgs e)
        {
            try
            {
                VectorItemsLayer VectorLayer = new VectorItemsLayer();
                mapControlVision.Layers.Add(VectorLayer);
                VectorLayer.Items.BeginUpdate();

                MapPushpin Pin = new DevExpress.XtraMap.MapPushpin();
                Pin.Location = new GeoPoint(double.Parse(txtLatitude.Text.Trim()), double.Parse(txtLongitude.Text.Trim()));

                Pin.Image = imageCollectionNewPin.Images[5];
                VectorLayer.Items.Add(Pin);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Lỗi Nhập Liệu", MessageBoxButtons.OK);
            }

        }

        private void mapControlVision_MouseMove(object sender, MouseEventArgs e)
        {
            
            //MapHitInfo info = this.mapControlVision.CalcHitInfo(e.Location);
            //MapPushpin dot = (MapPushpin)info.MapPushpin;
            //txtLatitude.Text = dot.Location.Latitude.ToString();
            //txtLongitude.Text = dot.Location.Longitude.ToString();
            //GeoPoint. p = new GeoPoint.
        }

        private void navBarItemUtilities_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e)
        {
            xtraTabControl.SelectedTabPage = xtraTabPageUtilities;
            xtraTabPageSetting.PageVisible = false;
            xtraTabPageUtilities.PageVisible = true;
            xtraTabPageViewDB.PageVisible = false;
            xtraTabPageVision.PageVisible = false;
        }

        private void navBarItemSetting_LinkClicked(object sender, DevExpress.XtraNavBar.NavBarLinkEventArgs e)
        {
            xtraTabControl.SelectedTabPage = xtraTabPageSetting;
            xtraTabPageSetting.PageVisible = true;
            xtraTabPageUtilities.PageVisible = false;
            xtraTabPageViewDB.PageVisible = false;
            xtraTabPageVision.PageVisible = false;
            
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            lblDistance.Text = Utils.CalculateDistance(double.Parse(txtLatitude1.Text), double.Parse(txtLongitude1.Text), double.Parse(txtLatitude2.Text), double.Parse(txtLongitude2.Text)).ToString() + " met";
        }
    }
}
